package com.ehomepay.xyxeample.common.redis.service.impl;

import com.ehomepay.xyxeample.common.redis.config.RedisConfig;
import com.ehomepay.xyxeample.common.redis.service.RedisClientTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisCluster;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2018/5/8.
 */

@Component
public class RedisClientTemplateImpl extends AbstractRedisClientTemplate implements RedisClientTemplate {

    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    @Autowired
    private JedisCluster jedisCluster;

    private String getPreKey(String key) {
        String tempPre = redisProperties.getPreKey();
        if (StringUtils.isEmpty(tempPre)) {
            return REDISPREKEY +":" + key;
        }
        tempPre = tempPre + ":";
        return tempPre + key;
    }

    @Override
    public String get(String key) {
        return jedisCluster.get(this.getPreKey(key));
    }

    @Override
    public String getNativeByKey(String key) {
        return jedisCluster.get(key);
    }

    @Override
    public void set(String key, String value) {
        jedisCluster.set(getPreKey(key), value);
    }

    @Override
    public void set(String key, String value, int time) {
        String tmpkey = getPreKey(key);
        jedisCluster.set(tmpkey, value);
        jedisCluster.expire(tmpkey, time);
    }

    @Override
    public boolean isExist(String key) {
        return jedisCluster.exists(getPreKey(key));
    }

    @Override
    public boolean delete(String key) {
        return jedisCluster.del(getPreKey(key)) == 1;
    }

    @Override
    public long putToListEnd(String key, String value) {
        return jedisCluster.rpush(getPreKey(key), value);
    }

    @Override
    public List<String> getListHead(String key) {
        List<String> result = jedisCluster.blpop(1000, getPreKey(key));
        if(null == result || result.isEmpty())
            return new ArrayList<String>();
        return result;
    }

    @Override
    public Long hset(String key, String field, String value) {
        return jedisCluster.hset(getPreKey(key), field, value);
    }

    @Override
    public String hset(String key, Map<String, String> values) {
        return jedisCluster.hmset(getPreKey(key), values);
    }

    @Override
    public String hget(String key, String field) {
        return jedisCluster.hget(getPreKey(key), field);
    }

    @Override
    public Map<String, String> hgetAll(String key) {
        return jedisCluster.hgetAll(getPreKey(key));
    }

    @Override
    public Long decr(String key) {
        return jedisCluster.decr(getPreKey(key));
    }

    @Override
    public Long incr(String key) {
        return jedisCluster.incr(getPreKey(key));
    }

    @Override
    public Long expire(String key, int seconds) {
        return jedisCluster.expire(getPreKey(key), seconds);
    }

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    @Override
    public boolean lock(String lockKey , String requestId , int timeout) {
        String result = jedisCluster.set(lockKey, requestId , SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, timeout);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

    private static final Long RELEASE_SUCCESS = 1L;

    @Override
    public boolean unlock(String key,String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedisCluster.eval(script, Collections.singletonList(key), Collections.singletonList(requestId));
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
}
